package org.newlucene.suggest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.newlucene.core.analysis.Token;
import org.newlucene.core.document.Document;
import org.newlucene.core.index.IndexReader;
import org.newlucene.core.index.Term;
import org.newlucene.core.search.BooleanSearcher;
import org.newlucene.core.search.ScoreDoc;
import org.newlucene.core.search.TermSearcher;
import org.newlucene.core.store.Directory;

/*
 * the suggested words are ranked with 3 criteria:
 * 1) gram boolean result score
 * 2) edit distance
 * 3) word frequency
 * 
 * An example, suppose we have the following words in the dictionary:
 * cased
 * casablanca
 * silence
 * encase
 * treble
 * blend
 * opulence
 * 
 * When we search for caseblenco, we get casablanca as the top suggestion.
 */
public class Suggester
{
//    /**
//     * Boost value for start and end grams
//     */
//    private float bStart = 2.0f;
//    private float bEnd = 1.0f;

    private IndexReader indexReader;
    
    public Suggester(Directory directory) throws IOException
    {
        this.indexReader = IndexReader.open(directory);
    }

    public void close() throws IOException
    {
    	this.indexReader.close();
    }
    
    /**
     * Suggest similar words
     * @param inputWord String the word you want a spell check done on
     * @param numSuggestions int the number of suggest words
     * @throws IOException
     * @return String[], if no words, return String[0]
     */
    public List<String> suggestSimilar (String inputWord, int numSuggestions) throws IOException
    {
    	String allGrams = Util.getAllGrams(inputWord);
    	
    	GramAnalyzer analyzer = new GramAnalyzer();
    	analyzer.set(allGrams);
    	List<Token> tokens = new ArrayList<Token>();
    	Token t;
    	while ((t = analyzer.next()) != null)
    	{
    		tokens.add(t);
    	}
    	
    	// construct searcher
    	BooleanSearcher booleanSearcher = new BooleanSearcher(indexReader);
    	for (Token token : tokens)
    	{
    		TermSearcher termSearcher = new TermSearcher(indexReader, new Term("gram", token.termText));
    		booleanSearcher.add(termSearcher, false, false);
    	}
    	
    	// do search
    	SuggestHitCollector hc = new SuggestHitCollector(inputWord, indexReader, numSuggestions);
    	booleanSearcher.search(hc);
    	
    	List<String> suggestedWords = new ArrayList<String>(numSuggestions);
        ScoreDoc[] scoreDocs = hc.getScoreDocs();
        for (ScoreDoc scoreDoc : scoreDocs)
        {
        	int docId = scoreDoc.getDocId();
        	Document doc = indexReader.document(docId);
        	String suggestedWord = doc.get("keyword");
        	if (!suggestedWord.equalsIgnoreCase(inputWord))	// don't suggest a word for itself, that would be silly
        	{
        		suggestedWords.add(suggestedWord);
        	}
        }
        return suggestedWords;
    }
}